package com.quanyan.stadium.service.impl;

import com.quanyan.api.APIResponse;
import com.quanyan.club.entity.RespClubBaseInfo;
import com.quanyan.club.service.ClubOpenService;
import com.quanyan.common.Plugin.PageObj;
import com.quanyan.common.utils.GsonUtils;
import com.quanyan.common.utils.HttpUtils;
import com.quanyan.common.utils.ObjectUtil;
import com.quanyan.redisCluster.utils.SerializeUtil;
import com.quanyan.stadium.api.resp.RespMyGameEvent;
import com.quanyan.stadium.biz.BizUserGameScheduleDao;
import com.quanyan.stadium.biz.redis.UserGameScheduleCacheDao;
import com.quanyan.stadium.constants.GameConstants;
import com.quanyan.stadium.entity.*;
import com.quanyan.stadium.entity.vo.*;
import com.quanyan.stadium.enums.GameCategoryConfigEnum;
import com.quanyan.stadium.enums.PkEventStatusEnum;
import com.quanyan.stadium.mapper.TbGameClubTeamUserMapper;
import com.quanyan.stadium.mapper.TbGameEventMapper;
import com.quanyan.stadium.mapper.TbGameEventTeamMapper;
import com.quanyan.stadium.mapper.TbUserGameScheduleMapper;
import com.quanyan.stadium.service.*;
import com.quanyan.stadium.service.commonComponent.BaseService;
import com.quanyan.stadium.service.commonComponent.ConfigService;
import com.quanyan.stadium.service.commonComponent.OfficialGameCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * Created by lei.w on 2016/7/13.
 */
@Service
public class UserCenterServiceImpl implements UserCenterService {
    private final Logger logger = LoggerFactory.getLogger(UserCenterServiceImpl.class);

    @Autowired
    BaseService baseService;
    @Autowired
    PKEventService pkEventService ;
    @Autowired
    private ClubOpenService clubOpenService;
    @Autowired
    PointsService pointsService;
    @Autowired
    private GradeIntegralService gradeIntegralService;
    @Autowired
    BizUserGameScheduleDao bizUserGameScheduleDao;
    @Autowired
    UserGameScheduleCacheDao userGameScheduleCacheDao;
    @Autowired
    ConfigService configService;
    @Autowired
    OfficialGameCache officialGameCache;

    @Autowired
    private TbGameEventMapper tbGameEventMapper;

    @Autowired
    private TbGameEventTeamMapper tbGameEventTeamMapper;

    @Autowired
    private TbGameClubTeamUserMapper tbGameClubTeamUserMapper;

    @Autowired
    private TbUserGameScheduleMapper tbUserGameScheduleMapper;

    @Override
    public List<GameSchedule> queryUserGameEventByUidAndStatus(Integer uid, Integer status, Integer pageNum, Integer pageSize) {

        if(ObjectUtil.isObjectEmpty(uid, status)) {
            logger.info("queryUserGameEventByUidAndStatus param uis or status is null. uid:"+uid+" status:"+status);
            return Collections.emptyList();
        }

        return changeListTbGameSchedule(bizUserGameScheduleDao.selectUserGameScheduleByUidAndStatus(uid, status, pageNum, pageSize));
    }

    @Override
    public List<GameSchedule> queryUserGameEventByUidAndStatus(Integer uid, Integer status) {
        if(ObjectUtil.isObjectEmpty(uid, status)) {
            logger.info("queryUserGameEventByUidAndStatus param uis or status is null. uid:"+uid+" status:"+status);
            return Collections.emptyList();
        }

        return changeListTbGameSchedule(bizUserGameScheduleDao.selectUserGameScheduleByUidAndStatus(uid, status));
    }

    @Override
    public List<UserGameRecord> queryUserGameRecord(Integer uid, Integer status, Integer pageNo, Integer pageSize) {
        List<UserGameRecord> userGameRecordList = getUserGameRecordList(uid, pageNo, pageSize);

        if (userGameRecordList.size() > 0) {
            return userGameRecordList;
        }

        UserGameRecord userGameRecord;
        Map<byte[], Double> map = new HashMap<>();
        List<PKEventVo> pkEventVoList = pkEventService.queryUserPKList(uid, PkEventStatusEnum.PK_STATUS_CONFIRM.getId());
        for (PKEventVo pkEventVo : pkEventVoList) {
            userGameRecord = new UserGameRecord();
            // 2 代表PK赛
            userGameRecord.setType(2);
            userGameRecord.setPkEventVo(pkEventVo);
            if (ObjectUtil.isNotObjectEmpty(pkEventVo.getBeginTime())) {
                map.put(SerializeUtil.serialize(userGameRecord), pkEventVo.getBeginTime().doubleValue());
            }
        }

        List<GameSchedule> gameScheduleList = queryUserGameEventByUidAndStatus(uid, status);
        for (GameSchedule gameSchedule : gameScheduleList) {
            userGameRecord = new UserGameRecord();
            userGameRecord.setType(1);
            userGameRecord.setGameSchedule(gameSchedule);

            if (ObjectUtil.isNotObjectEmpty(gameSchedule.getStartTime())) {
                map.put(SerializeUtil.serialize(userGameRecord), gameSchedule.getStartTime().doubleValue());
            }
        }

        userGameScheduleCacheDao.putUserGameRecordSet(uid, map);

        return getUserGameRecordList(uid, pageNo, pageSize);
    }

    @Override
    public UserCenter queryUserInfo(Integer uid, Integer categoryId) {
        UserCenter userCenter = new UserCenter();
        try {
            userCenter = new UserCenter();
            User user = new User();
            BeanUtils.copyProperties(baseService.queryUserMsg(uid), user);
            user.setRespCity(baseService.getRespCityById(user.getAreaId()));
            userCenter.setUser(user);
            userCenter.setScore(pointsService.getPointsByCategoryIdAndUserIds(uid, categoryId));
            userCenter.setGrade(gradeIntegralService.getUserGradeInfo(uid, categoryId).getGrade());
            try {
                userCenter.setClubBaseInfo(clubOpenService.getSportClubsOfAdmin(uid, categoryId));
            } catch (Exception ex){
                logger.error("queryUserInfo getClubBaseInfoByUserId is failed. ex:", ex);
            }

        }catch (Exception e) {
            logger.error("queryUserInfo is failed. e", e);
        }

        return userCenter;
    }

    @Override
    public PageObj queryNearbyUser(Integer uid, NearbyUser nearbyUser) {

        if (nearbyUser.getType().byteValue() == GameConstants.TEAM_TYPE_PERSON) {
            return PageObj.create(0,nearbyUser.getPageNo(), nearbyUser.getPageSize(), queryNearby(uid, nearbyUser)) ;
        }

        if (nearbyUser.getType().byteValue() == GameConstants.TEAM_TYPE_CLUB) {
            try{

                PageObj<List<RespClubBaseInfo>> pageObj = clubOpenService.getPKClubs(nearbyUser.getCityId(),nearbyUser.getCategoryId(), nearbyUser.getPageNo(), nearbyUser.getPageSize());

                List<RespClubBaseInfo> list = pageObj.getItems();
                if (ObjectUtil.isNotObjectEmpty(nearbyUser.getClubId(), list) && list.size() > 0) {
                    for (int i = 0; i < list.size(); i++) {
                        RespClubBaseInfo clubBaseInfo = list.get(i);
                        if (nearbyUser.getClubId().intValue() == clubBaseInfo.getClubId().intValue()) {
                            list.remove(i);
                        }
                    }
                }

                return pageObj;

            } catch (Exception e) {
                logger.error("queryNearbyUser  getPKClubs is failed. e:", e);
            }
        }

        return new PageObj();
    }

    @Override
    public PageObj<List<RespMyGameEvent>> getMyGameEventList(Integer uid,Integer pageNum, Integer pageSize) {
        List<RespMyGameEvent> respMyGameEvents = new ArrayList<>();

        //创建三个容器，分别存放不同状态的比赛
        //进行中的比赛
        List<RespMyGameEvent> gameEventListStarting = new ArrayList<>();
        //未开始的比赛
        List<RespMyGameEvent> gameEventListNotStart = new ArrayList<>();
        //已结束的比赛
        List<RespMyGameEvent> gameEventListEnding = new ArrayList<>();

        List<Integer> gameEventIdList = new ArrayList<>();

        //查询我创建的比赛
        List<TbGameEvent> tbGameEventList = this.selectGameEvent(uid,null);
        if(null != tbGameEventList && tbGameEventList.size() > 0){
            for(TbGameEvent gameEvent : tbGameEventList){
                gameEventIdList.add(gameEvent.getId());
            }
        }

        //处理我创建的比赛
        //if(null != tbGameEventList || tbGameEventList.size() > 0){
        //   this.handleGameEvents(tbGameEventList,gameEventListStarting,gameEventListNotStart,gameEventListEnding);
        //}

        //查询我参加的比赛

        //小球已报名比赛
        TbGameEventTeamExample tbGameEventTeamExample = new TbGameEventTeamExample();
        TbGameEventTeamExample.Criteria criteria_smallBall = tbGameEventTeamExample.createCriteria();
        criteria_smallBall.andTypeEqualTo(GameConstants.TEAM_TYPE_PERSON);
        criteria_smallBall.andUidEqualTo(uid);
        List<TbGameEventTeam> tbGameEventTeamList = tbGameEventTeamMapper.selectByExample(tbGameEventTeamExample);

        if(null != tbGameEventTeamList && tbGameEventTeamList.size() > 0){
            for(TbGameEventTeam tbGameEventTeam : tbGameEventTeamList){
                gameEventIdList.add(tbGameEventTeam.getGameEventId().intValue());
            }
        }
        //大球已报名比赛
        TbGameClubTeamUserExample tbGameClubTeamUserExample = new TbGameClubTeamUserExample();
        TbGameClubTeamUserExample.Criteria criteria_bigBall = tbGameClubTeamUserExample.createCriteria();
        criteria_bigBall.andUidEqualTo(uid);
        tbGameClubTeamUserExample.setDistinct(true);
        List<TbGameClubTeamUser> tbGameClubTeamUserList = tbGameClubTeamUserMapper.selectByExample(tbGameClubTeamUserExample);
        if (null != tbGameClubTeamUserList && tbGameClubTeamUserList.size() >0 ){
            for (TbGameClubTeamUser gameClubTeamUser : tbGameClubTeamUserList){
                gameEventIdList.add(gameClubTeamUser.getGameEventId());
            }
        }

        //处理我参加的比赛
        if(gameEventIdList.size() > 0){
            List<TbGameEvent> gameEvents = this.selectGameEvent(null,gameEventIdList);
            this.handleGameEvents(gameEvents,gameEventListStarting,gameEventListNotStart,gameEventListEnding);
        }

        //  对进行中/为开始的比赛按时间排序
        Collections.reverse(gameEventListEnding);

        //将所有状态的比赛合并起来
        respMyGameEvents.addAll(gameEventListStarting);
        respMyGameEvents.addAll(gameEventListNotStart);
        respMyGameEvents.addAll(gameEventListEnding);

        //把数据分页
        int total = respMyGameEvents.size();
        if(total > (pageNum+1)*pageSize){
            respMyGameEvents = respMyGameEvents.subList(pageNum*pageSize,(pageNum+1)*pageSize);
        }else if(total > pageNum*pageSize && total <= (pageNum+1)*pageSize){
            respMyGameEvents = respMyGameEvents.subList(pageNum*pageSize,total);
        }else {
            respMyGameEvents.clear();
        }

        return PageObj.create(total,pageNum,pageSize,respMyGameEvents);
    }

    private void handleGameEvents(List<TbGameEvent> tbGameEventList,List<RespMyGameEvent> gameEventListStarting,List<RespMyGameEvent> gameEventListNotStart,List<RespMyGameEvent> gameEventListEnding) {
        Long currentTime = new Date().getTime();
        for (TbGameEvent gameEvent : tbGameEventList) {
            if (gameEvent.getCurrentRoundId().byteValue() == GameConstants.GAME_EVENT_ZERO.byteValue()) {
                gameEventListEnding.add(this.structureGameEvent(gameEvent, GameConstants.GAME_EVENT_END));
            } else {
                if (currentTime < gameEvent.getStartTime().getTime()) {
                    gameEventListNotStart.add(this.structureGameEvent(gameEvent, GameConstants.GAME_EVENT_SIGN));
                } else {
                    gameEventListStarting.add(this.structureGameEvent(gameEvent, GameConstants.GAME_EVENT_START));
                }
            }
        }
    }

    private RespMyGameEvent structureGameEvent(TbGameEvent gameEvent,Byte status) {
        RespMyGameEvent respMyGameEvent = new RespMyGameEvent();
        try {
            respMyGameEvent.setCategoryId(gameEvent.getCategoryId());
            respMyGameEvent.setGameEventId(gameEvent.getId());
            respMyGameEvent.setClubId(gameEvent.getClubId());
            respMyGameEvent.setStatus(status);
            respMyGameEvent.setType(gameEvent.getType());
            GameEvent gameEventInfo = officialGameCache.getGameEvent(gameEvent.getId());
            if(null != gameEventInfo){
                respMyGameEvent.setClubName(gameEventInfo.getName());
                respMyGameEvent.setLogoUrl(gameEventInfo.getGameEventHost().getImage().getImageUrl());
                respMyGameEvent.setLimitNum(gameEventInfo.getTeamLimitNum());
                respMyGameEvent.setJoinedNum(gameEvent.getTeamLimitNum() - gameEvent.getInventoryLevel());
                Byte payType = gameEventInfo.getPayTypeModel().getPayType();
                respMyGameEvent.setPayType(payType);
                if(payType == 0){
                    respMyGameEvent.setPrice(gameEventInfo.getPrice());
                }
                respMyGameEvent.setStartTime(gameEventInfo.getStartTime());
                respMyGameEvent.setEndTime(gameEventInfo.getEndTime());
                String score = gameEventInfo.getGameGradeLevel().getDesc();
                if(score.equals("无等级限制")){
                    score = "";
                }
                respMyGameEvent.setGameGradeLevelType(score);
                Boolean isTeam = true;
                Integer gameCategoryType = gameEventInfo.getGameCategory().getGameCategoryType();
                if(null != gameCategoryType){
                    if(gameCategoryType == GameCategoryConfigEnum.CONFIG_GAME_CATEGORY_NOT_KNOW_ONLY.getId() ||
                            gameCategoryType == GameCategoryConfigEnum.CONFIG_GAME_CATEGORY_MALE_ONLY.getId() ||
                            gameCategoryType == GameCategoryConfigEnum.CONFIG_GAME_CATEGORY_FEMALE_ONLY.getId()){
                        isTeam = false;
                    }
                }
                respMyGameEvent.setIsTeam(isTeam);
            }
        }catch (Exception e){
            logger.error("structureGameEvent is failed. e:", e);
        }
        return respMyGameEvent;
    }


    private List<TbGameEvent> selectGameEvent(Integer uid,List<Integer> ids){
        TbGameEventExample tbGameEventExample = new TbGameEventExample();
        TbGameEventExample.Criteria criteria = tbGameEventExample.createCriteria();
        criteria.andIsDeleteEqualTo(GameConstants.IS_NOT_DELETE);
        //tbGameEventExample.setDistinct(true);
        if(null != uid){
            criteria.andUidEqualTo(uid);
        }
        if(null != ids && ids.size() > 0){
            criteria.andIdIn(ids);
        }
        tbGameEventExample.setOrderByClause(" start_time asc ");
        return tbGameEventMapper.selectByExample(tbGameEventExample);
    }

    private List<UserGameRecord> getUserGameRecordList(Integer uid, Integer pageNo, Integer pageSize) {

        List<UserGameRecord> userGameRecordList = Collections.emptyList();
        Set<byte[]> userGameList = userGameScheduleCacheDao.queryUserGameRecordSetInterval(uid, pageSize*(pageNo), pageSize);

        if (userGameList.size() == 0) {
            return userGameRecordList;
        }

        userGameRecordList = new ArrayList<>();
        for (byte[] userGameRecord : userGameList) {
            userGameRecordList.add((UserGameRecord)SerializeUtil.unserialize(userGameRecord));
        }

        return userGameRecordList;
    }

    private List<GameSchedule> changeListTbGameSchedule(List<TbUserGameSchedule> tbUserGameScheduleList) {

        List<GameSchedule> gameScheduleList = Collections.emptyList();
        if (tbUserGameScheduleList == null || tbUserGameScheduleList.size() == 0) {
            logger.info("queryUserGameEventByUidAndStatus result list is null.");
            return gameScheduleList;
        }

        gameScheduleList = new ArrayList<>();
        GameSchedule gameSchedule;
        GameEvent gameEvent;
        for (TbUserGameSchedule tbUserGameSchedule : tbUserGameScheduleList) {
            try{
                gameEvent = officialGameCache.getGameEvent(tbUserGameSchedule.getGameEventId());
                gameSchedule = officialGameCache.getGameSchedule(tbUserGameSchedule.getGameScheduleId(), gameEvent.getGameTeamType());

                if (ObjectUtil.isObjectEmpty(gameSchedule, gameEvent)) {
                    continue;
                }

                gameSchedule.setId(tbUserGameSchedule.getGameScheduleId());
                gameSchedule.setGameId(tbUserGameSchedule.getGameEventId());
                gameSchedule.setGameName(tbUserGameSchedule.getGameName());
                gameSchedule.setRecordStatus(tbUserGameSchedule.getScheduleStatus());
                gameSchedule.setIsAccess(tbUserGameSchedule.getIsAccess());
                gameSchedule.setType(tbUserGameSchedule.getType());
                gameSchedule.setCategoryId(tbUserGameSchedule.getGameCategoryId());
                gameSchedule.setGameEventType(tbUserGameSchedule.getGameEventType());
                gameSchedule.setRecordAuth(tbUserGameSchedule.getRecordAuth());
                gameSchedule.setCurTime(System.currentTimeMillis());

//                PlaceUnitInfo placeUnitInfo = new PlaceUnitInfo();
//                if (ObjectUtil.isObjectEmpty(gameSchedule.getPlaceUnitInfo()) && ObjectUtil.isNotObjectEmpty(gameEvent.getPlaceInfo())) {
//                    BeanUtils.copyProperties(gameEvent.getPlaceInfo(), placeUnitInfo);
//                    gameSchedule.setPlaceUnitInfo(placeUnitInfo);
//                }

                gameScheduleList.add(gameSchedule);

            } catch (Exception e) {
                logger.error("changeListTbGameSchedule is failed. e:", e);
            }
        }

        return gameScheduleList;
    }

    private List<UserCenter> queryNearby(Integer uid, NearbyUser nearbyUser) {

        List<UserCenter> userCenterList = Collections.emptyList();

        try{
            // TODO 修改为配置表
//        String url = "http://192.168.30.201/homepage/serverNearbyPlayerList.api";
            String url = configService.getProperty("user.center.nearby.url", "http://192.168.30.201/homepage/serverNearbyPlayerList.api");
            APIResponse apiResponse = GsonUtils.jsonStrToEntity(HttpUtils.sendWebRequestByPostJsonStr(null, url, GsonUtils.toJson(nearbyUser)), APIResponse.class);

            if (apiResponse.isRet() && apiResponse.getData() != null) {
                userCenterList = new ArrayList<>();
                List<Map<String, Object>> list;
                list = (List) ((Map<String, Object>)apiResponse.getData()).get("resultlist");

                UserCenter userCenter = null;
                for (Map<String, Object> m : list) {
                    if (null == m || null == m.get("uid")) {
                        break;
                    }

                    Double nUid = (Double) m.get("uid");
                    if (uid.intValue() != nUid.intValue()) {
                        userCenter =  queryUserInfo(nUid.intValue(), nearbyUser.getCategoryId());
                        if (ObjectUtil.isNotObjectEmpty(userCenter.getUser(), userCenter.getUser().getUid())) {
                            userCenterList.add(userCenter);
                        }
                    }
                }
            }

            logger.info("queryNearby userCenterList:"+ userCenterList);
        } catch (Exception e) {
            logger.error("queryNearby is failed. e:", e);
        }

        return userCenterList;
    }
}
